package com.bingoogolapple.qrcode.core;

import ohos.agp.utils.Point;
import ohos.app.Context;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraAbility;
import ohos.media.camera.device.FrameConfig;
import ohos.media.camera.params.Metadata;
import ohos.media.image.common.ImageFormat;
import ohos.media.image.common.Size;

import java.util.Collection;
import java.util.List;

public class CameraConfigurationManager {
    private final Context mContext;
    private Point mCameraResolution;
    private Point mPreviewResolution;
    private FrameConfig.Builder framePreviewConfigBuilder;
    private CameraKit cameraKit;

    CameraConfigurationManager(Context context) {
        mContext = context;
    }

    void initFromCameraParameters(Camera camera) {
        Point screenResolution = BGAQRCodeUtil.getScreenResolution(mContext);
        Point screenResolutionForCamera = new Point(screenResolution.getPointX(),
                screenResolution.getPointY());

        if (BGAQRCodeUtil.isPortrait(mContext)) {
            screenResolutionForCamera = new Point(screenResolution.getPointY(),
                    screenResolution.getPointX());
        }

        CameraAbility cameraAbility = cameraKit.getCameraAbility("0");
        mPreviewResolution = getPreviewResolution(cameraAbility.getSupportedSizes(ImageFormat.JPEG), screenResolutionForCamera);

        if (BGAQRCodeUtil.isPortrait(mContext)) {
            mCameraResolution = new Point(mPreviewResolution.getPointY(), mPreviewResolution.getPointX());
        } else {
            mCameraResolution = mPreviewResolution;
        }
    }

    private static boolean autoFocusAble(Camera camera, CameraKit cameraKit) {
        CameraAbility cameraAbility = cameraKit.getCameraAbility("0");
        int[] afMode = cameraAbility.getSupportedAfMode();
        return afMode.length > 0;
    }

    Point getCameraResolution() {
        return mCameraResolution;
    }

    void setDesiredCameraParameters(Camera camera) {

    }

    /**
     * Selects the most suitable preview frames per second range, given the desired frames per
     * second.
     *
     * @param camera            the camera to select a frames per second range from
     * @param desiredPreviewFps the desired frames per second for the camera preview frames
     * @return the selected preview frames per second range
     */
    private int[] selectPreviewFpsRange(Camera camera, float desiredPreviewFps) {
        // The camera API uses integers scaled by a factor of 1000 instead of floating-point frame
        // rates.
        int desiredPreviewFpsScaled = (int) (desiredPreviewFps * 1000.0f);
        return null;
    }

    void openFlashlight(Camera camera) {
        doSetTorch(camera, true);
    }

    void closeFlashlight(Camera camera) {
        doSetTorch(camera, false);
    }

    private void doSetTorch(Camera camera, boolean newSetting) {
        if(framePreviewConfigBuilder == null)
        {
            return;
        }
        framePreviewConfigBuilder.setFlashMode(Metadata.FlashMode.FLASH_ALWAYS_OPEN);
    }

    private static String findSettableValue(Collection<String> supportedValues, String... desiredValues) {
        String result = null;
        if (supportedValues != null) {
            for (String desiredValue : desiredValues) {
                if (supportedValues.contains(desiredValue)) {
                    result = desiredValue;
                    break;
                }
            }
        }
        return result;
    }

    private int getDisplayOrientation() {
        return  0;

    }

    private static Point getPreviewResolution(List<Size> supportSizeList, Point screenResolution) {
        Point previewResolution =
                findBestPreviewSizeValue(supportSizeList, screenResolution);
        if (previewResolution == null) {
            previewResolution = new Point((screenResolution.getPointXToInt() >> 3) << 3, (screenResolution.getPointYToInt() >> 3) << 3);
        }
        return previewResolution;
    }

    private static Point findBestPreviewSizeValue(List<Size> supportSizeList, Point screenResolution) {
        int bestX = 0;
        int bestY = 0;
        int diff = Integer.MAX_VALUE;
        for (Size previewSize : supportSizeList) {

            int newX = previewSize.width;
            int newY = previewSize.height;

            int newDiff = Math.abs(newX - screenResolution.getPointXToInt()) + Math.abs(newY - screenResolution.getPointYToInt());
            if (newDiff == 0) {
                bestX = newX;
                bestY = newY;
                break;
            } else if (newDiff < diff) {
                bestX = newX;
                bestY = newY;
                diff = newDiff;
            }

        }

        if (bestX > 0 && bestY > 0) {
            return new Point(bestX, bestY);
        }
        return null;
    }
}
